package com.leyou.search.service.Impl;

import com.leyou.common.dto.PageDTO;
import com.leyou.item.client.ItemFeignClient;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpecParamDTO;
import com.leyou.item.dto.SpuDTO;

import com.leyou.search.entity.Goods;
import com.leyou.search.repository.GoodsRepository;
import com.leyou.search.service.IndexService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class IndexServiceImpl implements IndexService {

    @Autowired
    private GoodsRepository goodsRepository;

    @Autowired
    private ItemFeignClient itemFeignClient;


    //创建索引库
    @Override
    public void contextLoads() {
        deleteAndCreatedIndex();
    }

    //导入数据到es
    @Override
    public void loadData() {

        long page = 1L;
        while (true) {
            PageDTO<SpuDTO> spuDTOPage = itemFeignClient.querySpuPage(page, 100L, null, null, null, null);

            if (spuDTOPage.getTotalPage() == 0) {
                break;
            }

            List<SpuDTO> itemList = spuDTOPage.getItems();
            // 遍历Spu集合，把SpuDTO通过buildGoods方法转为Goods
            List<Goods> goodsList = itemList
                    .stream()
                    .map(this::buildGoods)
                    .collect(Collectors.toList());
            //批量写入es
            goodsRepository.saveAll(goodsList);
            page++;

            if (page > spuDTOPage.getTotalPage()) {
                break;
            }
        }




    }

    //SpuDTO转为Goods
    public Goods buildGoods(SpuDTO spuDTO) {
        Goods goods = new Goods();
        BeanUtils.copyProperties(spuDTO,goods);

        //主体名称
        String dtoName = spuDTO.getName();
        //categoryId 商品分类，包含id和name
        goods.setCategoryId(spuDTO.getCid3());
        //suggestion 自动补全的候选字段，可以包含多个值，
        List<String> suggestionList = new ArrayList<>();
        // 例如:主体名称，品牌+主体，品牌+分类，分类+品牌
        String brandName =
                StringUtils.substringBefore(spuDTO.getBrandName(),"（");//品牌
        String categoryName =
                StringUtils.substringBefore(spuDTO.getCategoryName(),"/");//分类
        suggestionList.add(dtoName);
        suggestionList.add(dtoName.startsWith(brandName) ? brandName : dtoName + brandName);
        suggestionList.add(brandName + categoryName);
        suggestionList.add(categoryName + brandName);
        goods.setSuggestion(suggestionList);

        //Title 商品标题，用于搜索
        goods.setTitle(dtoName + " " + brandName + " " + categoryName);

        //一个spu下至少有一个sku
        List<SkuDTO> skuDTOList = itemFeignClient.querySkuListBySpuID(spuDTO.getId());
        Long sold = 0L;
        Set<Long> hashSet = new HashSet<>();
        for (SkuDTO skuDTO : skuDTOList) {
            hashSet.add(skuDTO.getPrice());
            sold += skuDTO.getSold();
        }

        //prices 商品spu中的所有sku的价格集合（滤重）
        goods.setPrices(hashSet);

        //sold spu下的多个sku的销量之和
        goods.setSold(sold);

        //image 商品预览图，从sku中取出第一个即可
        goods.setImage(StringUtils.substringBefore(skuDTOList.get(0).getImages(), ","));

        //updateTime
        goods.setUpdateTime(new Date());

        //specs 规格参数的key和value对，用于过滤
        List<SpecParamDTO> specSearchParamDTOList = itemFeignClient.querySpuValuesBySpuId(spuDTO.getId(), true);

        List<Map<String, Object>> mapList = specSearchParamDTOList
                .stream()
                .map(specSearchParamDTO -> {
                    Map<String, Object> hashMap = new HashMap<>();
                    hashMap.put("name", specSearchParamDTO.getName());
                    //value如果是数值，有区间，选择区间
                    hashMap.put("value", chooseSegment(specSearchParamDTO));
                    return hashMap;
                }).collect(Collectors.toList());

        goods.setSpecs(mapList);

        return goods;
    }




    //处理数值value 有区间，选择区间
    private Object chooseSegment(SpecParamDTO p) {
        Object value = p.getValue();
        if (value == null || StringUtils.isBlank(value.toString())) {
            return "其它";
        }
        if (!p.getNumeric() || StringUtils.isBlank(p.getSegments()) || value instanceof Collection) {
            return value;
        }
        double val = parseDouble(value.toString());
        String result = "其它";
        // 保存数值段
        for (String segment : p.getSegments().split(",")) {
            String[] segs = segment.split("-");
            // 获取数值范围
            double begin = parseDouble(segs[0]);
            double end = Double.MAX_VALUE;
            if (segs.length == 2) {
                end = parseDouble(segs[1]);
            }
            // 判断是否在范围内
            if (val >= begin && val < end) {
                if (segs.length == 1) {
                    result = segs[0] + p.getUnit() + "以上";
                } else if (begin == 0) {
                    result = segs[1] + p.getUnit() + "以下";
                } else {
                    result = segment + p.getUnit();
                }
                break;
            }
        }
        return result;
    }

    private double parseDouble(String str) {
        try {
            return Double.parseDouble(str);
        } catch (Exception e) {
            return 0;
        }
    }






    private void deleteAndCreatedIndex() {
        try {
            //先删除再创建索引库
            goodsRepository.deleteIndex();
        } catch (Exception e) {
        }

        goodsRepository.createIndex("{\n" +
                "  \"settings\": {\n" +
                "    \"analysis\": {\n" +
                "      \"analyzer\": {\n" +
                "        \"my_pinyin\": {\n" +
                "          \"tokenizer\": \"ik_smart\",\n" +
                "          \"filters\": [\n" +
                "            \"py\"\n" +
                "          ]\n" +
                "        }\n" +
                "      },\n" +
                "      \"filters\": {\n" +
                "        \"py\": {\n" +
                "\t\t  \"type\": \"pinyin\",\n" +
                "          \"keep_full_pinyin\": true,\n" +
                "          \"keep_joined_full_pinyin\": true,\n" +
                "          \"keep_original\": true,\n" +
                "          \"limit_first_letter_length\": 16,\n" +
                "          \"remove_duplicated_term\": true\n" +
                "        }\n" +
                "      }\n" +
                "    }\n" +
                "  },\n" +
                "  \"mappings\": {\n" +
                "    \"properties\": {\n" +
                "      \"id\": {\n" +
                "        \"type\": \"keyword\"\n" +
                "      },\n" +
                "      \"suggestion\": {\n" +
                "        \"type\": \"completion\",\n" +
                "        \"analyzer\": \"my_pinyin\",\n" +
                "        \"search_analyzer\": \"ik_smart\"\n" +
                "      },\n" +
                "      \"title\":{\n" +
                "        \"type\": \"text\",\n" +
                "        \"analyzer\": \"my_pinyin\",\n" +
                "        \"search_analyzer\": \"ik_smart\"\n" +
                "      },\n" +
                "      \"image\":{\n" +
                "        \"type\": \"keyword\",\n" +
                "        \"index\": false\n" +
                "      },\n" +
                "      \"updateTime\":{\n" +
                "        \"type\": \"date\"\n" +
                "      },\n" +
                "      \"specs\":{\n" +
                "        \"type\": \"nested\",\n" +
                "        \"properties\": {\n" +
                "          \"name\":{\"type\": \"keyword\" },\n" +
                "          \"value\":{\"type\": \"keyword\" }\n" +
                "        }\n" +
                "      }\n" +
                "    }\n" +
                "  }\n" +
                "}");
    }


    //上架
    @Override
    public void itemUp(Long supId) {
        if (supId != null) {
           //根据spuId查询
           // SpuDTO spuDTO = itemFeignClient.querySpuBySpuID(supId);
            PageDTO<SpuDTO> spuDTOPage = itemFeignClient.querySpuPage(1L, 1L, null, null, supId, true);

            if (spuDTOPage.getTotalPage() == 1) {
                //把查询到的spuDTO取出转换为goods并保存
                SpuDTO spuDTO = spuDTOPage.getItems().get(0);
                goodsRepository.save(buildGoods(spuDTO));
            }
        }
    }
    //下架
    @Override
    public void itemDown(Long supId) {
        if (supId != null) {
            goodsRepository.deleteById(supId);
        }
    }

}
